package cn.com.nes.site.module.service.contract;

import cn.com.nes.common.util.OssUtil;
import cn.com.nes.common.util.ParameterUtil;
import cn.com.nes.common.util.id.IdUtils;
import cn.com.nes.mybatis.agent.contract.entity.ContractAuditRecord;
import cn.com.nes.mybatis.agent.contract.entity.ContractInfo;
import cn.com.nes.mybatis.agent.contract.entity.ContractSerialNumber;
import cn.com.nes.mybatis.agent.contract.entity.ContractType;
import cn.com.nes.mybatis.agent.contract.mapper.ContractAuditRecordMapper;
import cn.com.nes.mybatis.agent.contract.mapper.ContractInfoMapper;
import cn.com.nes.mybatis.agent.contract.mapper.ContractSerialNumberMapper;
import cn.com.nes.mybatis.agent.contract.mapper.ContractTypeMapper;
import cn.com.nes.site.entity.DataReq;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.bo.contract.ContractQueryPageBO;
import cn.com.nes.site.module.dao.crm.OpportunityDaoImpl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class ContractService {

    @Resource
    ContractInfoMapper contractInfoMapper;

    @Resource
    ContractTypeMapper contractTypeMapper;

    @Resource
    ContractSerialNumberMapper contractSerialNumberMapper;

    @Resource
    ContractAuditRecordMapper contractAuditRecordMapper;

    @Resource
    private OpportunityDaoImpl opportunityDaoImpl;

    public PageData getContractList(DataReq req) {

        int pageId = req.getPageid();
        int pageSize = req.getPagesize();

        String companyId = req.getUinfo().getCompanyId();
        String userId = req.getUinfo().getId();

        String id = ParameterUtil.getString(req, "id");

        String contractNumber = ParameterUtil.getString(req, "contractNumber");
        String contractName = ParameterUtil.getString(req, "name");
        Integer contractType = ParameterUtil.getInteger(req, "type");
        String companyName = ParameterUtil.getString(req, "companyName");
        String creatorName = ParameterUtil.getString(req, "creatorName");
        Integer contractState = ParameterUtil.getInteger(req, "state");
        Integer auditState = ParameterUtil.getInteger(req, "auditState");
        String opportunityId = ParameterUtil.getString(req, "businessId");
        String customerId = ParameterUtil.getString(req, "customerId");

        // 菜单，1-台账，2-审核，3-我的
        Integer menu = ParameterUtil.getInteger(req, "menu");

        ContractQueryPageBO contractQueryPageBo = new ContractQueryPageBO();
        contractQueryPageBo.setId(id);
        contractQueryPageBo.setContractNumber(contractNumber);
        contractQueryPageBo.setContractName(contractName);
        contractQueryPageBo.setAuditState(auditState);
        contractQueryPageBo.setContractType(contractType);
        contractQueryPageBo.setCompanyName(companyName);
        contractQueryPageBo.setCreatorName(creatorName);
        contractQueryPageBo.setContractState(contractState);
        contractQueryPageBo.setMenu(menu);
        contractQueryPageBo.setOpportunityId(opportunityId);
        contractQueryPageBo.setCustomerId(customerId);
        contractQueryPageBo.setOperateUserId(Long.valueOf(userId));
        contractQueryPageBo.setOperateUserCompanyId(req.getUinfo().getCompanyType().equals("00") ? "" : companyId);


        Page<Map<String, Object>> page = new Page<>(pageId, pageSize);
        List<Map<String, Object>> result =
                contractInfoMapper.getContractList(page, contractQueryPageBo);

        for (Map<String, Object> contract : result) {
            // 审核状态
            switch ((Integer) contract.get("auditState")) {
                case 0:
                    contract.put("auditStateDesc", "未审核");
                    break;
                case 1:
                    contract.put("auditStateDesc", "审核通过");
                    break;
                default:
                    contract.put("auditStateDesc", "审核未通过");
            }
            // 转换合同状态
            if ((Integer) contract.get("terminated") == 1) {
                contract.put("state", 3);
            } else {
                Date effectiveDate = (Date) contract.get("effectiveDate");
                Date terminationDate = (Date) contract.get("terminationDate");
                final long now = System.currentTimeMillis();
                if (effectiveDate != null && terminationDate != null) {
                    if (effectiveDate.getTime() > now) {
                        contract.put("state", 0);
                    } else if (terminationDate.getTime() > now) {
                        contract.put("state", 1);
                    } else {
                        contract.put("state", 2);
                    }
                } else if (effectiveDate != null) {
                    contract.put("state", effectiveDate.getTime() > now ? 0 : 1);
                } else if (terminationDate != null) {
                    contract.put("state", terminationDate.getTime() > now ? 1 : 2);
                } else {
                    contract.put("state", 1);
                }
            }

            // 生成oss路径
            String ossPath = (String) contract.get("ossPath");
            if (StrUtil.isNotBlank(ossPath)) {
                final String fileSignURL = OssUtil.getFileSignURL(ossPath, 0);
                contract.put("fileURL", fileSignURL);
            }

            // 查询详情时，额外查询审核情况
            if (StrUtil.isNotBlank(id)) {
                QueryWrapper<ContractAuditRecord> wrapper = new QueryWrapper<>();
                wrapper.eq(ContractAuditRecord.CONTRACT_ID, id);
                wrapper.orderByDesc(ContractAuditRecord.GMT_CREATE);
                wrapper.last("limit 1");
                List<ContractAuditRecord> contractAuditRecords = contractAuditRecordMapper.selectList(wrapper);
                contract.put("auditComment", CollUtil.isNotEmpty(contractAuditRecords) ? contractAuditRecords.get(0).getAuditComment() : "");
            }
        }

        page.setRecords(result);

        return PageData.ok(page);
    }


    @Transactional(value = "transactionManager_newg", rollbackFor = Exception.class)
    public PageData saveContract(DataReq req) {
        PageData pageData = new PageData();

        String id = ParameterUtil.getString(req, "id");

        // 用户信息
        String creatorId = req.getUinfo().getId();
        String companyId = req.getUinfo().getCompanyId();

        // 合同编号
        String contractNumber = ParameterUtil.getString(req, "contractNumber");
        if (StrUtil.isEmpty(id) && !"".equals(contractNumber)) {
            int cnt = contractInfoMapper.isDontractNumberDouble(contractNumber, companyId);
            if (cnt > 0) {
                pageData.setRetCode(9);
                pageData.setRetMessage("合同编号重复！");
                return pageData;
            }
        }
        if (StrUtil.isBlank(id) && StrUtil.isBlank(contractNumber)) {
            contractNumber = generateContractNumber(req);
        }
        // 合同名称
        String name = ParameterUtil.getString(req, "name");
        // 合同类型
        Integer type = ParameterUtil.getInteger(req, "type");
        // 对方公司名称
        String companyName = ParameterUtil.getString(req, "companyName");
        // 对方公司联系人
        String contactPerson = ParameterUtil.getString(req, "contactPerson");
        // 合同金额
        BigDecimal contractAmount = ParameterUtil.getDecimal(req, "contractAmount");
        // 合同生效日
        Date effectiveDate = ParameterUtil.getDate(req, "effectiveDate");
        // 合同终止日
        Date terminationDate = ParameterUtil.getDate(req, "terminationDate");
        // 合同原件oss路径
        String ossPath = ParameterUtil.getString(req, "ossPath");

        // 合同文件名
//        String fileName = ParameterUtil.getString(req, "fileName");
        String fileName = ParameterUtil.getString(req, "filename");

        // 关联商机的id
        String opportunityId = ParameterUtil.getString(req, "opportunityId");

        // 关联客户的ID
        String customerId = ParameterUtil.getString(req, "customerId");

        ContractInfo contractInfo;
        // 新增
        if (StrUtil.isBlank(id)) {
            contractInfo = new ContractInfo(companyId, contractNumber, name, type, companyName, contactPerson,
                    contractAmount, Long.parseLong(creatorId), 0, effectiveDate, terminationDate, 0,
                    ossPath, 0, opportunityId, customerId);
            contractInfo.setFileName(StrUtil.emptyToNull(fileName));
            contractInfo.setId(IdUtils.uuid());
            contractInfoMapper.insert(contractInfo);
            //修改相关商机的状态为商机成交
            opportunityDaoImpl.chageOpportunityStage(opportunityId, "03");
        }
        // 更新
        else {
            contractInfo = contractInfoMapper.selectById(id);
            if (contractInfo == null) {
                pageData.setRetCode(9);
                pageData.setRetMessage("合同不存在");
                return pageData;
            }
            if (contractInfo.getAuditState() == 1) {
                pageData.setRetCode(9);
                pageData.setRetMessage("已过审合同无法修改");
                return pageData;
            }
            contractInfo = new ContractInfo();
            contractInfo.setId(id);
            contractInfo.setName(StrUtil.emptyToNull(name));
            contractInfo.setType(type);
            contractInfo.setCompanyName(StrUtil.emptyToNull(companyName));
            contractInfo.setContactPerson(StrUtil.emptyToNull(contactPerson));
            contractInfo.setContractAmount(contractAmount);
            contractInfo.setEffectiveDate(effectiveDate);
            contractInfo.setTerminationDate(terminationDate);
            contractInfo.setOssPath(StrUtil.emptyToNull(ossPath));
            contractInfo.setAuditState(0);
            contractInfo.setFileName(StrUtil.emptyToNull(fileName));
            contractInfo.setOpportunityId(StrUtil.emptyToNull(opportunityId));

            contractInfoMapper.updateById(contractInfo);
        }


        pageData.setRetCode(0);
        pageData.setRetMessage("OK" + "-" + contractNumber); // 返回合同编号
        return pageData;
    }


    @Transactional(value = "transactionManager_newg", rollbackFor = Exception.class)
    public String generateContractNumber(DataReq req) {
        String companyId = req.getUinfo().getCompanyId();
        // 合同编号规则，前缀+年份+流水号，默认前缀为"HT-"
        String prefix = ParameterUtil.getString(req, "prefix", "HT-");
        if ('-' != prefix.charAt(prefix.length() - 1)) {
            prefix = prefix + "-";
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int year = calendar.get(Calendar.YEAR);

        ContractSerialNumber contractSerialNumber = new ContractSerialNumber();
        QueryWrapper<ContractSerialNumber> wrapper = new QueryWrapper<>();
        wrapper.eq(ContractSerialNumber.COMPANY_ID, companyId)
                .eq(ContractSerialNumber.YEAR, year)
                .eq(ContractSerialNumber.PREFIX, prefix)
                .eq(ContractSerialNumber.DELETED, 0);

        List<ContractSerialNumber> contractSerialNumberList = contractSerialNumberMapper.selectList(wrapper);
        if (ObjectUtil.isNotEmpty(contractSerialNumberList)) {
            contractSerialNumber = contractSerialNumberList.get(0);
        }

        // 流水号不存在，新建流水号
        if (CollUtil.isEmpty(contractSerialNumberList)) {
            contractSerialNumber = new ContractSerialNumber();
            contractSerialNumber.setSerialNumber(1);
            contractSerialNumber.setCompanyId(companyId);
            contractSerialNumber.setPrefix(prefix);
            contractSerialNumber.setYear(year);
            contractSerialNumber.setDeleted(0);
            contractSerialNumberMapper.insert(contractSerialNumber);
        } else {
            contractSerialNumber.setSerialNumber(contractSerialNumber.getSerialNumber() + 1);
            contractSerialNumberMapper.updateById(contractSerialNumber);
        }
        Integer serialNumber = contractSerialNumber.getSerialNumber();
        return prefix + year + "-" + StrUtil.padPre(String.valueOf(serialNumber), 4, '0');
    }

    public PageData terminateContract(DataReq req) {
        PageData res = new PageData();

        String id = ParameterUtil.getString(req, "id");
        final ContractInfo contractInfo = contractInfoMapper.selectById(id);
        if (contractInfo != null) {
            contractInfo.setTerminated(1);
            contractInfoMapper.updateById(contractInfo);

            res.setRetCode(0);
            res.setRetMessage("OK");
            return res;
        }
        res.setRetCode(9);
        res.setRetMessage("合同不存在");
        return res;
    }

    public PageData deleteContract(DataReq req) {
        PageData res = new PageData();

        String id = ParameterUtil.getString(req, "id");
        final ContractInfo contractInfo = contractInfoMapper.selectById(id);
        if (contractInfo != null) {
            contractInfo.setContractNumber(contractInfo.getContractNumber() + System.currentTimeMillis());
            contractInfo.setDeleted(1);
            contractInfoMapper.updateById(contractInfo);

            res.setRetCode(0);
            res.setRetMessage("OK");
            return res;
        }
        res.setRetCode(9);
        res.setRetMessage("合同不存在");
        return res;
    }

    @Transactional(value = "transactionManager_newg", rollbackFor = Exception.class)
    public PageData auditContract(DataReq req) {
        PageData res = new PageData();

        String id = ParameterUtil.getString(req, "id");
        final ContractInfo contractInfo = contractInfoMapper.selectById(id);
        if (contractInfo == null) {
            res.setRetCode(9);
            res.setRetMessage("OK");
            return res;
        }

        String auditComment = ParameterUtil.getString(req, "auditComment");
        Boolean pass = ParameterUtil.getBoolean(req, "pass");

        // 修改审核状态
        contractInfo.setGmtModified(null);
        contractInfo.setAuditState(Boolean.TRUE.equals(pass) ? 1 : 2);
        contractInfo.updateById();

        // 添加审核记录
        ContractAuditRecord record = new ContractAuditRecord();
        record.setContractId(contractInfo.getId());
        record.setAuditComment(auditComment);
        record.setCompanyId(contractInfo.getCompanyId());
        record.setPassed(Boolean.TRUE.equals(pass) ? 1 : 0);
        record.setUserId(Long.parseLong(req.getUinfo().getId()));
        record.insert();

        res.setRetCode(0);
        res.setRetMessage("OK");
        return res;
    }

    public PageData getContractTypes(DataReq req) {
        PageData res = new PageData();

        String companyID = req.getUinfo().getCompanyId();

        QueryWrapper<ContractType> wrapper = new QueryWrapper<>();
        wrapper.select("id", ContractType.TYPE_CODE + " as typeCode", ContractType.NAME, ContractType.REMARKS)
                .eq(ContractType.COMPANY_ID, companyID);
        final List<Map<String, Object>> contractTypes = contractTypeMapper.selectMaps(wrapper);

        res.setPage(contractTypes);
        res.setRetCode(0);
        res.setRetMessage("OK");
        return res;
    }

    public PageData saveContractType(DataReq req) {
        PageData res = new PageData();

        String companyID = req.getUinfo().getCompanyId();

        Integer id = ParameterUtil.getInteger(req, "id");

        String name = ParameterUtil.getString(req, "name");
        String remarks = ParameterUtil.getString(req, "remarks");

        ContractType contractType = new ContractType();
        contractType.setName(name);
        contractType.setRemarks(remarks);
        contractType.setCompanyId(companyID);

        // 新增
        if (id == null) {
            // 获取当前最大的type code
            QueryWrapper<ContractType> wrapper = new QueryWrapper<>();
            wrapper.eq(ContractType.COMPANY_ID, companyID)
                    .orderByDesc(ContractType.TYPE_CODE)
                    .last("limit 1");
            final List<ContractType> contractTypes = contractTypeMapper.selectList(wrapper);
            int latestCode = 0;
            if (CollUtil.isNotEmpty(contractTypes)) {
                latestCode = contractTypes.get(0).getTypeCode();
            }

            contractType.setTypeCode(latestCode + 1);
            contractType.insert();
        } else {
            contractType.setId(id);
            contractType.updateById();
        }


        res.setRetCode(0);
        res.setRetMessage("OK");
        return res;
    }

    public PageData deleteContractType(DataReq req) {
        PageData res = new PageData();

        Integer id = ParameterUtil.getInteger(req, "id");

        contractTypeMapper.deleteById(id);

        res.setRetCode(0);
        res.setRetMessage("OK");
        return res;
    }

}
